// 创建响应式数据
let resultA = 0
// 创建依赖响应式数据的方法effect
const effectA = () => { resultA = obj.a * 100 }
// 目的 为了当obj中的数据发生变化时结果都会随之变化

// 1、追踪变量
let targetMaps = new WeakMap   // 这里放置追踪的对象
let activeEffect = null

// 2、由于再需要时候才添加响应函数--定义响应函数
const effect = (eff) => {
    activeEffect = eff
    activeEffect()
    activeEffect = null
}
const trigger = (target, key) => {
    let depMaps = targetMaps.get(target)
    if(depMaps){
        let dep = depMaps.get(key)
        if(dep){
            dep.forEach(effect => effect())
        }
    }
}
const track = (target, key) => {
    if(activeEffect){
        // 这里是被激活的响应式函数
        let depMaps = targetMaps.get(target)    // 这里判断targetMap中是否存在target这个目标对象
        if(!depMaps){
            targetMaps.set(target, depMaps = new Map)
        }
        let dep = depMaps.get(key)  // 获取depMap是否含有该属性
        if(!dep){
            depMaps.set(key, dep = new Set)
        }
        dep.add(activeEffect)
    }

}

// 3、第2步定义了追踪喝触发更新函数，却只能手动调用，因此做成自动调用
const reactive = (obj) => {
    if(typeof obj !== 'object') return
    return new Proxy(obj, {
        get(target, key ,receiver) {
            // 追踪属性
            track(target,key)
            return Reflect.get(target, key, receiver)
        },
        set(target,key,value,receiver){
            let oldValue = target[key]
            let isSetValue = Reflect.set(target, key, value, receiver)
            if(oldValue !== value) {
                trigger(target,key) // 触发更新函数
                return isSetValue
            }
        }
    })
}

// 4、这是针对reactive中只能放对象，针对于简单数据类型使用ref，ref不是reactive({value:})
const ref = (raw) => {
    let obj = {
        get value() {
            track(obj, 'value')
            return raw
        },
        set value(newValue) {
            raw = newValue
            trigger(obj, 'value')
            return newValue
        }
    }
    return obj
}

// 5、定义computed
const computed = (getter) => {
    let result = ref()
    effect(() => { return result.value = getter })
    return result
}
let name = ref('张三')
let obj = reactive({ a:1, get b() { return this.a } })
obj.a = 10
name.value = '李四'
effect(effectA)
console.log(name.value,'value')
console.log('resultA',resultA)
